package com.example.java_gobang.api;

import com.example.java_gobang.game.Match;
import com.example.java_gobang.game.OnlineUserManager;
import com.example.java_gobang.game.Room;
import com.example.java_gobang.game.RoomManager;
import com.example.java_gobang.model.GameReadyResponse;
import com.example.java_gobang.model.GameResponse;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;

@Component
public class GameAPI extends TextWebSocketHandler {


    private ObjectMapper objectMapper = new ObjectMapper();
    private  boolean secondHall = false;
    private  boolean secondGame = false;

    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;
    @Resource
    private UserMapper userMapper;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

            GameReadyResponse gameReadyResponse = new GameReadyResponse();
            User user = (User) session.getAttributes().get("user");;

            //用户未登陆
            if (user == null) {
                gameReadyResponse.setOk(false);
                gameReadyResponse.setReason("用户尚未登录!");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyResponse)));

                return;
            }

            //判断用户是否已经进入房间
            WebSocketSession roomSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(user.getUserId());
            WebSocketSession hallSeesion = onlineUserManager.getWebSocketSessionByUserIdInGameHall(user.getUserId());
            if (roomSession != null){

                System.out.println("用户想重复进入游戏房间！");

                gameReadyResponse.setOk(false);
                gameReadyResponse.setReason("用户还没有匹配到！");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyResponse)));
            }

            //判断用户是否多开

            if (roomSession != null && hallSeesion != null) {
                System.out.println("用户尝试多开");
                gameReadyResponse.setOk(true);
                gameReadyResponse.setReason("不允许多开！");
                gameReadyResponse.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyResponse)));
            }


            //先设置玩家上线
            onlineUserManager.enterGameRoom(user.getUserId(),session);
            Room room = roomManager.getRoomByUserId(user.getUserId());
            //接着把两个玩家放入匹配队列中
            //因为一个房间可能会被多个线程访问，因此需要加锁
            synchronized (room){
                //通过 room 获得两个玩家，判断玩家1 和玩家2 是否加入游戏
                if (room.getUser1() == null){
                    // 把先连入房间的玩家作为先手方.
                    room.setWhiteUser(user.getUserId());
                    //把用户当作玩家1 加入
                    room.setUser1(user);
                    System.out.println("玩家 " + user.getUsername() + " 已经准备就绪! 作为玩家1");
                    return;
                }
                if (room.getUser2() == null){;
                    //把用户当作玩家2 加入
                    room.setUser2(user);
                    System.out.println("玩家 " + user.getUsername() + " 已经准备就绪! 作为玩家2");

                    // 当两个玩家都加入成功之后, 就要让服务器, 给这两个玩家都返回 websocket 的响应数据.
                    // 通知这两个玩家说, 游戏双方都已经准备好了.
                    // 通知玩家1
                    noticeGameReady(room, room.getUser1(), room.getUser2());
                    // 通知玩家2
                    noticeGameReady(room, room.getUser2(), room.getUser1());

                }
            }

    }


    //通知玩家
    private void noticeGameReady(Room room, User thisUser, User thatUser) throws IOException {
        GameReadyResponse gameReadyResponse = new GameReadyResponse();
        gameReadyResponse.setMessage("gameReady");
        gameReadyResponse.setOk(true);
        gameReadyResponse.setReason("");
        gameReadyResponse.setRoomId(room.getRoomId());
        gameReadyResponse.setThisUserId(thisUser.getUserId());
        gameReadyResponse.setThatUserId(thatUser.getUserId());
        gameReadyResponse.setWhiteUser(room.getWhiteUser());
        // 把当前的响应数据传回给玩家.
        WebSocketSession webSocketSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(thisUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyResponse)));
    }


    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //处理落子请求
         User user = (User) session.getAttributes().get("user");
         if (user == null){
             System.out.println("当前用户没有登录");
             return;
         }
         Room room1 = roomManager.getRoomByUserId(user.getUserId());
         //处理落子请求
         room1.putchess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 玩家下线
        User user = (User)session.getAttributes().get("user");
        if (user == null){
            System.out.println("当前用户没有登录");
            return;
        }
        WebSocketSession gameSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(user.getUserId());
        if (gameSession == session){
            onlineUserManager.exitGameRoom(user.getUserId());
        }

        System.out.println("当前用户 " + user.getUsername() + " 游戏房间连接异常!");
        // 通知对手获胜了
        noticeThatUserWin(user);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 玩家下线
        User user = (User)session.getAttributes().get("user");
        if (user == null){
            System.out.println("当前用户没有登录");
            return;
        }
        WebSocketSession gameSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(user.getUserId());
        if (gameSession == session){
            onlineUserManager.exitGameRoom(user.getUserId());
        }

        System.out.println("当前用户 " + user.getUsername() + " 离开游戏房间!");
        // 通知对手获胜了
        noticeThatUserWin(user);
    }

    private void noticeThatUserWin(User user) throws IOException {
        // 1. 根据当前玩家, 找到玩家所在的房间
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if (room == null) {
            // 这个情况意味着房间已经被释放了, 也就没有 "对手" 了
            System.out.println("当前房间已经释放, 无需通知对手!");
            return;
        }

        // 2. 根据房间找到对手
        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();
        // 3. 找到对手的在线状态
        WebSocketSession webSocketSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(thatUser.getUserId());
        if (webSocketSession == null) {
            // 这就意味着对手也掉线了!
            System.out.println("对手也已经掉线了, 无需通知!");
            return;
        }
        // 4. 构造一个响应, 来通知对手, 你是获胜方
        GameResponse resp = new GameResponse();
        resp.setMessage("putChess");
        resp.setUserId(thatUser.getUserId());
        resp.setWinner(thatUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

        // 5. 更新玩家的分数信息
        int winUserId = thatUser.getUserId();
        int loseUserId = user.getUserId();
        userMapper.win(winUserId);
        userMapper.lose(loseUserId);

        // 6. 释放房间对象
        Room room1 = roomManager.getRoomByUserId(user.getUserId());
        roomManager.removeTwoUserBattle(room1,room1.getUser1(),room1.getUser2());
    }



}


